package cn.tedu.csmall.stock.webapi.controller;

import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import cn.tedu.csmall.commons.restful.JsonResult;
import cn.tedu.csmall.commons.restful.ResponseCode;
import cn.tedu.csmall.stock.service.IStockService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.google.gson.stream.JsonToken;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.swing.text.html.HTMLDocument;

@RestController
@RequestMapping("/base/stock")
@Api(tags = "库存管理")
public class StockController {
    @Autowired
    private IStockService stockService;

    @GetMapping("/reduce/count")
    @ApiOperation("减少商品库存数")
    // @SentinelResource注解要标记控制层的方法才能生效,会在该方法运行时,被Sentinel管理
    // 这个控制器方法第一次运行后,会在Sentinel仪表台中看到限流选项
    // "减少商品库存数",会定义仪表台中代表该方法的选项名称
    // blockHandler能够指定当前方法被限流时运行的方法名称
    @SentinelResource(value = "减少商品库存数",blockHandler = "blockError",
                        fallback = "fallbackError")
    public JsonResult reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO){
        // 调用业务逻辑层
//        try {
//            Thread.sleep(5000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        // 测试Sentinel服务降级的随机异常
//        if(Math.random()<0.5){
//            // 如果发生异常,会运行服务降级的方法
//            throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,
//                    "随机异常");
//        }

        stockService.reduceCommodityCount(stockReduceCountDTO);
        return JsonResult.ok("库存减少已执行");
    }

    // Sentinel 自定义限流方法,规则如下
    // 1.访问修饰符必须是public
    // 2.返回值类型必须和控制器方法一致
    // 3.方法名必须和对应的限流控制器方法定义的blockHandler属性值一致
    // 4.方法的参数列表必须和控制器一致,而且还要额外添加BlockException类型的参数
    public JsonResult blockError(StockReduceCountDTO stockReduceCountDTO,
                                 BlockException e){
        // 运行这个方法就是被限流了,直接返回被限流的提示即可
        return JsonResult.failed(ResponseCode.INTERNAL_SERVER_ERROR,
                            "服务器忙,请稍后再试");
    }

    // 降级方法:上面@SentinelResource中fallback指定的降级方法
    // 声明格式:和限流方法基本相同,方法参数不需要添加异常类型
    // 当控制器方法发生异常时,Sentinel会自动调用这个方法
    // 在实际业务中,可以是运行新版本代码的过程中发送异常后,转而运行老版本代码的机制
    public JsonResult fallbackError(StockReduceCountDTO stockReduceCountDTO,
                                    Throwable throwable){
        throwable.printStackTrace();
        // 因为没有老版本代码,所以这里仅仅是输出降级提示
        return JsonResult.failed(ResponseCode.INTERNAL_SERVER_ERROR,
                    "运行发生异常,服务降级");
    }



}
